package com.base.lib.base.widget

import android.content.Context
import android.graphics.*
import android.graphics.drawable.BitmapDrawable
import android.os.Environment
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import android.widget.ImageView
import com.base.lib.base.BaseApplication
import java.io.File
import java.io.FileNotFoundException
import java.io.FileOutputStream
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.*

class PaintView : View {
    private var mCanvas: Canvas? = null
    private var mPath: Path? = null
    private var mBitmapPaint: Paint? = null
    private var mBitmap: Bitmap? = null

    //路径对象
    var isPaint = false //是否开始画过
        private set
    private var mPaint: Paint? = null
    private var savePath: ArrayList<DrawPath> = ArrayList<DrawPath>()
    private var deletePath: ArrayList<DrawPath> = ArrayList<DrawPath>()
    private var dp: DrawPath? = null
    private var mX = 0f
    private var mY = 0f
    private var bitmapWidth = 0
    private var bitmapHeight = 0
    private var imageView: ImageView? = null

    constructor(c: Context) : super(c) {
        initCanvas()
    }

    constructor(c: Context?, attrs: AttributeSet?) : super(c, attrs) {
        initCanvas()
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        bitmapWidth = MeasureSpec.getSize(widthMeasureSpec)
        bitmapHeight = MeasureSpec.getSize(heightMeasureSpec)
        val min = Math.min(bitmapWidth, bitmapHeight)
        if (mBitmap == null && min != 0) {
            mBitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888)
            mBitmap!!.setHasAlpha(true)
            mCanvas = Canvas(mBitmap!!) //所有mCanvas画的东西都被保存在了mBitmap中
            mCanvas!!.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
        }
//        val min1 = Math.min(widthMeasureSpec, heightMeasureSpec)
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
    }

    //初始化画布
    fun initCanvas() {
        bitmapWidth = width
        bitmapHeight = height
        isPaint = false
        mPaint = Paint()
        mPaint!!.isAntiAlias = true
        mPaint!!.isDither = true
        mPaint!!.color = Color.BLACK
        mPaint!!.style = Paint.Style.STROKE
        mPaint!!.strokeJoin = Paint.Join.ROUND
        mPaint!!.strokeCap = Paint.Cap.ROUND
        mPaint!!.strokeWidth = 10f
        val min = Math.min(bitmapWidth, bitmapHeight)
        if (mBitmap != null && min != 0) {
            mBitmap = Bitmap.createBitmap(bitmapWidth, bitmapHeight, Bitmap.Config.ARGB_8888)
            mBitmap!!.setHasAlpha(true)
            mCanvas = Canvas(mBitmap!!) //所有mCanvas画的东西都被保存在了mBitmap中
            mCanvas!!.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
        }
        mPath = Path()
        mBitmapPaint = Paint(Paint.DITHER_FLAG)
    }

    override fun onDraw(canvas: Canvas) {
        canvas.drawColor(Color.WHITE)
        if (mBitmap != null) {
            canvas.drawBitmap(mBitmap!!, 0f, 0f, mBitmapPaint) //显示旧的画布
            if (mPath != null) {
                // 实时的显示
                canvas.drawPath(mPath!!, mPaint!!)
            }
        }
    }

    fun setImageView(imageView: ImageView?) {
        this.imageView = imageView
    }

    internal inner class DrawPath {
        var path: Path? = null
        var paint: Paint? = null
    }

    /**
     * 撤销的核心思想就是将画布清空，
     * 将保存下来的Path路径最后一个移除掉，
     * 重新将路径画在画布上面。
     */
    fun undo() {
        println(savePath!!.size.toString() + "--------------")
        if (savePath != null && savePath!!.size > 0) {
            //调用初始化画布函数以清空画布
            initCanvas()

            //将路径保存列表中的最后一个元素删除 ,并将其保存在路径删除列表中
            val drawPath = savePath!![savePath!!.size - 1] as DrawPath
            deletePath.add(drawPath)
            savePath!!.removeAt(savePath!!.size - 1)

            //将路径保存列表中的路径重绘在画布上
            val iter: Iterator<*> = savePath!!.iterator() //重复保存
            while (iter.hasNext()) {
                val dp = iter.next() as DrawPath
                mCanvas!!.drawPath(dp.path!!, dp.paint!!)
            }
            invalidate() // 刷新
        }
    }

    /**
     * 恢复的核心思想就是将撤销的路径保存到另外一个列表里面(栈)，
     * 然后从redo的列表里面取出最顶端对象，
     * 画在画布上面即可
     */
    fun redo() {
        if (deletePath.size > 0) {
            //将删除的路径列表中的最后一个，也就是最顶端路径取出（栈）,并加入路径保存列表中
            val dp = deletePath[deletePath.size - 1] as DrawPath
            savePath.add(dp)
            //将取出的路径重绘在画布上
            mCanvas!!.drawPath(dp.path!!, dp.paint!!)
            //将该路径从删除的路径列表中去除
            deletePath.removeAt(deletePath.size - 1)
            invalidate()
        }
    }

    /*
     * 清空的主要思想就是初始化画布
     * 将保存路径的两个List清空
     * */
    fun removeAllPaint() {
        //调用初始化画布函数以清空画布
        initCanvas()
        invalidate() //刷新
        savePath!!.clear()
        deletePath.clear()
    }

    /*
     * 保存所绘图形
     * 返回绘图文件的存储路径
     * */
    fun saveBitmap(): String {
        //获得系统当前时间，并以该时间作为文件名
        val formatter = SimpleDateFormat("yyyyMMddHHmmss")
        val curDate = Date(System.currentTimeMillis()) //获取当前时间
        var str = "paint" + formatter.format(curDate) + ".png"
        var paintPath = ""
        var SDPATH: String = BaseApplication.getContext().getExternalFilesDir(Environment.DIRECTORY_PICTURES).toString()
        val dir: File = File("$SDPATH/paint/")
        val file: File = File("$SDPATH/paint/", str)
        if (!dir.exists()) {
            dir.mkdir()
        } else {
            if (file.exists()) {
                file.delete()
            }
        }
        try {
            val out = FileOutputStream(file)
            mBitmap!!.compress(Bitmap.CompressFormat.PNG, 100, out)
            out.flush()
            out.close()
            //保存绘图文件路径
            paintPath = "$SDPATH/paint/$str"
        } catch (e: FileNotFoundException) {
            e.printStackTrace()
        } catch (e: IOException) {
            e.printStackTrace()
        }
        return paintPath
    }

    private fun touch_start(x: Float, y: Float) {
        mPath!!.reset() //清空path
        mPath!!.moveTo(x, y)
        mX = x
        mY = y
    }

    private fun touch_move(x: Float, y: Float) {
        val dx = Math.abs(x - mX)
        val dy = Math.abs(y - mY)
        if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
            //mPath.quadTo(mX, mY, x, y);
            mPath!!.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2) //源代码是这样写的，可是我没有弄明白，为什么要这样？
            mX = x
            mY = y
        }
    }

    private fun touch_up() {
        mPath!!.lineTo(mX, mY)
        mCanvas!!.drawPath(mPath!!, mPaint!!)
        dp?.let { savePath.add(it) }
        mPath = null
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        val x = event.x
        val y = event.y
        when (event.action) {
            MotionEvent.ACTION_DOWN -> {
                isPaint = true
                mPath = Path()
                dp = DrawPath()
                dp!!.path = mPath
                dp!!.paint = mPaint
                touch_start(x, y)
                invalidate() //清屏
            }
            MotionEvent.ACTION_MOVE -> {
                touch_move(x, y)
                invalidate()
            }
            MotionEvent.ACTION_UP -> {
                touch_up()
                invalidate()
                if (imageView != null) {
                    val bd = BitmapDrawable(mBitmap)
                    imageView!!.setImageDrawable(bd)
                }
            }
        }
        return true
    }

    companion object {
        private const val TOUCH_TOLERANCE = 4f
    }
}
